package com.power.leopard.remote;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.power.leopard.ConfigManagerLoader;
import com.power.leopard.config.ConfigManager;
import com.power.leopard.constants.Constants;
import com.power.leopard.extension.ExtensionLoader;
import com.power.leopard.remote.common.codec.SerializerFactory;
import com.power.leopard.remote.listener.ShutdownHookListener;
import com.power.leopard.remote.provider.ProviderProcessHandlerFactory;

public final class ProviderBootStrap {

	private static volatile boolean isInitialized = false;
	static Server httpServer;
	private static volatile Map<String, Server> serversMap = new HashMap<String, Server>();

	public static void init() {
		if (!isInitialized) {
			SerializerFactory.init();
			ProviderProcessHandlerFactory.init();
			ConfigManager configManager = ConfigManagerLoader.getConfigManager();

			
			Thread shutdownHook = new Thread(new ShutdownHookListener());
			shutdownHook.setDaemon(true);
			shutdownHook.setPriority(Thread.MAX_PRIORITY);
			Runtime.getRuntime().addShutdownHook(shutdownHook);

			ServerConfig serverConfig = new ServerConfig();
			serverConfig.setProtocol(Constants.PROTOCOL_HTTP);

			List<Server> servers = ExtensionLoader.getExtensionList(Server.class);
			for (Server server : servers) {
				if (!server.isStarted() && server.support(serverConfig)) {
					server.start(serverConfig);
					httpServer = server;
					serversMap.put(serverConfig.getProtocol() + serverConfig.getPort(), server);
				}
			}
			isInitialized = true;
		}
	}

	public static ServerConfig startup(ProviderConfig<?> providerConfig) {
		ServerConfig serverConfig = providerConfig.getServerConfig();
		if (serverConfig == null) {
			throw new IllegalArgumentException("Server config is required.");
		}

		String protocol = serverConfig.getProtocol();
		int port = serverConfig.getPort();

		Server server = serversMap.get(protocol + port);
		if (server == null) {
			List<Server> servers = ExtensionLoader.getExtensionList(Server.class);
			for (Server s : servers) {
				if (!s.isStarted() && s.support(serverConfig)) {
					s.addService(providerConfig);
					s.start(serverConfig);
					serversMap.put(serverConfig.getProtocol() + serverConfig.getPort(), s);
				}
			}
		}

		server = serversMap.get(serverConfig.getProtocol() + serverConfig.getPort());
		if (server != null) {
			return server.getServerConfig();
		}
		return null;
	}
}
